//////////////////////////////////////////////
// GridLayout.h
//
//////////////////////////////////////////////

/// Defines / Macros -------------------------

#pragma once

/// Forward decl -----------------------------

namespace nkMaths
{
	class Rectangle ;
}

namespace nkWinUi
{
	class LayoutResizeHandle ;
}

/// Includes ---------------------------------

// nkWinUi
#include "../Dll/DllDefines.h"

#include "Layout.h"

// nkMaths
#include <NilkinsMaths/Geometry/Point.h>

// nkMemory
#include <NilkinsMemory/Containers/BufferCast.h>

#include <NilkinsMemory/Pointers/UniquePtr.h>

// Standards
#include <unordered_map>
#include <vector>

/// Internals --------------------------------

namespace nkWinUi
{
	struct GridLayoutEntryInfo
	{
		Component* _component = nullptr ;

		unsigned int _position [2] ;
		unsigned int _size [2] ;

		nkMemory::UniquePtr<LayoutResizeHandle> _handles [4] ;
	} ;
}

/// Class ------------------------------------
	
namespace nkWinUi
{
	class DLL_WINUI_EXPORT GridLayout final : public Layout
	{		
		public :
		
			// Constructor, destructor
			GridLayout (System* system) noexcept ;
			GridLayout (const GridLayout&) = delete ;
			virtual ~GridLayout () ;

			// Getters
			Component* getComponentAt (unsigned int index) const ;
			Component* getComponentAt (unsigned int x, unsigned int y) const ;
			unsigned int getGridWidth () const ;
			unsigned int getGridHeight () const ;
			float getFixedSizeRow (unsigned int index) const ;
			float getFixedSizeCol (unsigned int index) const ;
			float getWeightRow (unsigned int index) const ;
			float getWeightCol (unsigned int index) const ;
			nkMaths::Point getCellCoordinatesForPoint (nkMaths::Point point) const ;

			// Setters
			virtual void setParentComponent (Component* parent) override ;
			void setGridWidth (unsigned int value) ;
			void setGridHeight (unsigned int value) ;
			void insertRow (unsigned int index) ;
			void insertCol (unsigned int index) ;
			void eraseRow (unsigned int index) ;
			void eraseCol (unsigned int index) ;
			void setFixedSizeRow (unsigned int rowIndex, float sizePix) ;
			void setFixedSizeCol (unsigned int colIndex, float sizePix) ;
			void setWeightRow (unsigned int rowIndex, float weight) ;
			void setWeightCol (unsigned int colIndex, float weight) ;
			void setInternalBorderWidth (float valuePix) ;
			void setInternalBorderHeight (float valuePix) ;
			void setIgnoreInternalBorderCell (unsigned int rowIndex, unsigned int colIndex, bool value) ;

			// Components
			void addComponent (Component* component, unsigned int x, unsigned int y, unsigned int width, unsigned int height, bool resizeAllowed = false, bool updateLayout = true) ;
			void updateComponentCellCoverage (Component* component, unsigned int x, unsigned int y, unsigned int width, unsigned int height, bool updateLayout = true) ;
			nkMaths::Rectangle getComponentCellCoverage (Component* component) const ;
			virtual void removeComponent (Component* component) override ;

			// Update
			virtual void update () override ;

			// Import / Export
			virtual void exportClassToTree (nkExport::Node* rootNode) override ;
			virtual void exportComponentsNodeEntry (nkExport::Node* rootNode) override ;
			virtual void importClassFromTree (nkExport::Node* rootNode) override ;
			virtual void processComponentsNodeEntry (nkExport::Node* rootNode) override ;

			// Operators
			GridLayout& operator= (const GridLayout&) = delete ;

		private :

			// Functions
			// Events
			static void _onResizeHandleActivation (GridLayout* layout, LayoutResizeHandle* caller, bool activation) ;
			static void _onResizeHandleMove (GridLayout* layout, LayoutResizeHandle* caller, float xOffset, float yOffset) ;

		private :

			// Children info
			nkMemory::BufferCast<nkMemory::UniquePtr<GridLayoutEntryInfo>> _grid ;

			// Fixed sizes for rows and cols
			std::vector<float> _fixedSizeRows ;
			std::vector<float> _fixedSizeCols ;
			// Weight for rows and cols
			std::vector<float> _weightRows ;
			std::vector<float> _weightCols ;
			// Border flags for rows and cols
			std::vector<std::vector<bool>> _ignoreBorderCells ;

			// Internal layout info
			nkMaths::Point _internalBorderSize ;
	} ;
}